package com.ms.db.usertype;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;

import com.xpec.c4.db.cfg.DBConfig;

/**
 * 把ArrayList转换为String<br>
 * 使用指定的分隔符，默认为";"
 * 
 * @author Bany
 * 
 */
public abstract class BasicToString implements java.io.Serializable,
		org.hibernate.usertype.UserType{

	private static final Log log = LogFactory.getLog(BasicToString.class);

	/**
	 * 
	 */
	private static final long serialVersionUID = 8497462434246458644L;

	/**
	 * CLOB类型
	 */
	protected static final int[] CLOB_TYPES = new int[] { Types.CLOB };

	/**
	 * VARCHAR类型
	 */
	protected static final int[] VARCHAR_TYPES = new int[] { Types.VARCHAR };

	/**
	 * LONGVARCHAR类型
	 */
	protected static final int[] LONGVARCHAR_TYPES = new int[] { Types.LONGVARCHAR };

	/**
	 * 分隔符
	 */
	protected static final String SPLITTER = DBConfig.splitters.get(0)
			.getSplitter();

	/**
	 * 分隔反转符
	 */
	protected static final String SPLITTER_RE = DBConfig.splitters.get(0)
			.getRechange();

	/**
	 * SQL类型<br>
	 * 定义了常用的CLOB_TYPES、VARCHAR_TYPES、LONGVARCHAR_TYPES;
	 */
	public abstract int[] sqlTypes();

	/**
	 * 返回的类
	 */
	public abstract Class<?> returnedClass();

	/**
	 * 把对象转换为字符串
	 * 
	 * @param obj
	 * @return
	 * 
	 * @2011-9-1 上午11:48:53
	 */
	protected abstract String assemble(Object obj);

	/**
	 * 把字符串转换为对象
	 * 
	 * @param value
	 * @return
	 * 
	 * @2011-9-1 上午11:49:08
	 */
	protected abstract Object parse(String value);

	/**
	 * 默认的上否相等判断
	 */
	public boolean equals(Object x, Object y) throws HibernateException {

		if (x == y)
			return true;

		if (x != null && y != null) {

			// 类不一样，也不相等
			if (!x.getClass().equals(y.getClass())) {
				return false;
			}

			// 如果是List，先比较长度
			if (x instanceof List) {
				if (((List<?>) x).size() != ((List<?>) y).size()) {
					return false;
				}
			}

			// 如果是Map，先比较长度
			if (x instanceof Map) {
				if (((Map<?, ?>) x).size() != ((Map<?, ?>) y).size()) {
					return false;
				}
			}

			// 最后是转成字符串来比较
			String xString = assemble(x);
			String yString = assemble(y);
			if (xString != null && xString.equals(yString)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 取值
	 */
	public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
			throws HibernateException, SQLException {
		String value = (String) rs.getString(names[0]);
		return parse(value);
	}

	/**
	 * 设值
	 */
	public void nullSafeSet(PreparedStatement st, Object value, int index)
	throws HibernateException, SQLException {
		if (value != null) {
			String str = assemble(value);
			// 只是提醒用，並不是真的有錯， mark 掉
//			if (log.isInfoEnabled()) {
//				if (str != null && str.length() > 500) {
//					log.info("value is too long :" + str.length() + " class:"
//							+ this + " owner:" + value + " str:" + str);
//				}
//			}
			st.setString(index, str);
		}else{  
			st.setString(index, null);
		}
		
	}

	public Object deepCopy(Object value) throws HibernateException {
		return value;
	}

	public boolean isMutable() {
		return false;
	}

	public Object assemble(Serializable arg0, Object arg1)
			throws HibernateException {
		return null;
	}

	public Serializable disassemble(Object arg0) throws HibernateException {
		return null;
	}

	public int hashCode(Object arg0) throws HibernateException {
		return 0;
	}

	public Object replace(Object original, Object target, Object owner)
			throws HibernateException {
		return original;
	}
	
	@SuppressWarnings("unchecked")
	public static <T, P extends BasicToString> T parse(Class<T> resultClass, Class<P> clazz, String input) throws Exception {
		P parser = clazz.newInstance();
		return (T)parser.parse(input);
	}

}
